<?php

/**
 * the SiteLoader file may be included in other files, in a way in which
 * the path to the configuration file may not be as specified. hence we need to just
 * check if the database configuration informaton is available before try to retrieve it
 * hence saving us the possibility of an error when requiring the file 
 */
// get the current directory path
$currentPath = str_replace("\\", "/", dirname(__FILE__)) . "/";

$endPos = 0; // try to determine the base root
// check if we are configuring a normal page
if (strpos($currentPath, "/pages/") != 0) { // if we are not configuring a page
    $endPos = strpos($currentPath, "/pages/");

// check if configuring a theme related document
} else if (strpos($currentPath, "/themes/") != 0) {
    $endPos = strpos($currentPath, "/themes/");

// check if configuring a cms related document
} else if (strpos($currentPath, "/cms/") != 0) {
    $endPos = strpos($currentPath, "/cms/");

// check if configuring a cms related document
} else if (strpos($currentPath, "/assets/") != 0) {
    $endPos = strpos($currentPath, "/assets/");
    
} else if (strpos($currentPath, "/core/") != 0) {
    $endPos = strpos($currentPath, "/core/");
}

$base = substr($currentPath, 0, $endPos + 1);
$prot = explode("/", $_SERVER['SERVER_PROTOCOL']);
$siteRoot = str_replace($_SERVER['DOCUMENT_ROOT'], "/", $base);
$siteRoot = str_replace("//", "/", $siteRoot);
$siteHost = strtolower($prot[0]) . "://" . $_SERVER['HTTP_HOST'];
$basePath = str_replace("//", "/", $_SERVER['DOCUMENT_ROOT'] . $siteRoot);


if (!isset($config)) {

    // require the database connection
    $configPath = $basePath . 'assets/config/config.php';
    
    if (!defined("CONFIG_PATH")) define("CONFIG_PATH", $configPath);
    //echo $configPath;
	
    if( file_exists($configPath) ) 
      require_once($configPath);
    else
      return;
}

if (!defined("SITE_ID")) {

    $pagesPath = $basePath . 'pages/';
    $pagesURL = $siteRoot . 'pages/';
    $corePath = $basePath . 'core/';
    $coreURL = $siteRoot . 'core/';
    $cmsPath = $basePath . 'cms/';
    $cmsURL = $siteRoot . 'cms/';
	$assetsPath = $basePath . 'assets/';
	$assetsURL = $siteRoot . 'assets/';
    $componentsPath = $basePath . 'assets/components/';
    $componentsURL = $siteRoot . 'assets/components/';
    $scriptPath = $basePath . 'assets/scripts/';
    $scriptURL = $siteRoot . 'assets/scripts/';
    $themesPath = $basePath . 'assets/themes/';
    $themesURL = $siteRoot . 'assets/themes/';
    $extPath = $basePath . 'assets/ext/';

    // define a globally easily accessible variables for the config file
    if (!defined("BASE_PATH")) define("BASE_PATH", $basePath);
    if (!defined("SITE_ROOT")) define("SITE_ROOT", $siteRoot);
    if (!defined("SITE_HOST")) define("SITE_HOST", $siteHost);
    if (!defined("PAGES_PATH")) define("PAGES_PATH", $pagesPath);
    if (!defined("PAGES_URL")) define("PAGES_URL", $pagesURL);
    if (!defined("CORE_PATH")) define("CORE_PATH", $corePath);
	if (!defined("CORE_URL")) define("CORE_URL", $coreURL);
    if (!defined("EXT_PATH")) define("EXT_PATH", $extPath);
    if (!defined("COMPONENTS_PATH")) define("COMPONENTS_PATH", $componentsPath);
    if (!defined("COMPONENTS_URL")) define("COMPONENTS_URL", $componentsURL);
    if (!defined("CMS_PATH")) define("CMS_PATH", $cmsPath);
    if (!defined("CMS_URL")) define("CMS_URL", $cmsURL);
    if (!defined("SCRIPTS_PATH")) define("SCRIPTS_PATH", $scriptPath);
    if (!defined("SCRIPTS_URL")) define("SCRIPTS_URL", $scriptURL);
    if (!defined("THEMES_PATH")) define("THEMES_PATH", $themesPath);
    if (!defined("THEMES_URL")) define("THEMES_URL", $themesURL);
	if (!defined("ASSETS_PATH")) define("ASSETS_PATH", $assetsPath);
    if (!defined("ASSETS_URL")) define("ASSETS_URL", $assetsURL);
}

/**
 * Records all previously imported classes and the path they were found at, to
 * prevent re-traversing of the system if already included in the current path
 */
$kan_imported_classes = array();


// register the kan_import functionality as an autoLoad function, so developers
// hardly need to use it explicitly.
spl_autoload_register('kan_import');

/**
 * Include the base classes needed to define a site in KAN and to provide
 * connectivity to the KAN database
 */
kan_import( array('Database','Controller','Model','Manager') ); // base classes for system
kan_import( array('ComponentsManager','SitesManager','StatsManager','SystemManager') ); // base controller implementations

/**
 * Preload the KAN ComponentManager and all possible components and create a global
 * reference to the manager to enable components be included easily via the getComponent
 * function call
 */
$compManager = new ComponentsManager();

/**
 * Preload the KAN SystemManager to enable users to obtain a system setting value
 */
$system = new SystemManager();

if (!defined("SEF_URLS")) {
    $sef = $system->getSetting("UseFriendlyURLs", false);
    $sef = ($sef == "true") ? true : false;

    if ($sef && !kan_is_rewrite_supported()) {
        trigger_error("URL REWRITING via the Apache Mod_Rewrite Module Is Not Supported. "
            . "The Search Engine Friendly URL Setting Cannot Be Used. <br />"
            . "Please Disable The Setting From The System Configuration In The CMS");

        $sef = false;
    }

    define("SEF_URLS", $sef);
}

/**
 * Provides a simple way to load classes when developing a theme or custom code
 *
 * @param string $className Class or Interface name automatically
 *              passed to this function by the PHP Interpreter
 */
function kan_import($className) {
    global $kan_imported_classes;
	
	// add support for importing multiple classes at once in the form
	// of an array list
	if( is_array($className) ) {
		foreach($className as $cn) {
			kan_import($cn);	
		}
		
		return;
	}
    
    if( @array_key_exists($className, $kan_imported_classes) ) {
        include_once( $kan_imported_classes[$className] );
        return;
    }
    
    //Directories added here must be relative to the script going to use this file
    $directories = array(
        //'',
        CORE_PATH,
		CORE_PATH . 'controllers/',
		CORE_PATH . 'models/',
        CORE_PATH . 'views/',
		CORE_PATH . 'helpers/',
		CORE_PATH . 'utils/',
        EXT_PATH . 'controllers/',
        EXT_PATH . 'models/',
        EXT_PATH . 'views/'
    );

    //Add your file naming formats here
    $fileNameFormats = array('%s.php'); //'%s.class.php', 'class.%s.php', '%s.inc');

    // if searching for a controller or view, make the process faster
    if( strstr($className, 'Controller') != false || strstr($className, 'Manager') != false ) {
        $directories = array(
            CORE_PATH . 'controllers/',
            EXT_PATH . 'controllers/'
        );
    }
    
    else if( strstr($className, 'View') != false ) {
        $directories = array(
            CORE_PATH . 'views/',
            EXT_PATH . 'views/'
        );
    }
    
    // this is to take care of the PEAR style of naming classes
    $path = str_ireplace('_', '/', $className);

    foreach ($directories as $directory) {
        foreach ($fileNameFormats as $fileNameFormat) {
            $path = $directory . sprintf($fileNameFormat, $className);
            if (file_exists($path)) {
                include_once $path;
                
                // cache record for later
                $kan_imported_classes[$className] = $path;
                return;
            }
        }
    }
    
    // if the file cannot be found in the specified pre lookup folders,
    // then check if a matching file exists in the current directory location
    if (@include_once ($path . '.php')) {
        return;
    }
}


/**
 * Checks to see if the apache rewrite module is loaded and can be used
 */
function kan_is_rewrite_supported() {

    $is_apache = strpos($_SERVER['SERVER_SOFTWARE'], "Apache") > -1;

    // take an educated guesses as to whether or not mod_rewrite is available
    if (!$is_apache)
        return false;

    if (function_exists('apache_get_modules')) {
        if (!in_array("mod_rewrite", apache_get_modules())) {
            return false;
        }
    }

    return true;
}

/**
 * Converts the supplied text to a plain text to help prevent Cross Site scripting.
 * Resulting text is also encoded in UTF-8 format.
 * 
 * @param mixed $text the data to convert
 * @return mixed a plain text string where HTML Elements are escaped
 */
function kan_make_plain($text) {
    return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}

/**
 * Takes any input and returns an cleaned out data. This is ideal for form or URL parameter
 * inputs. This function strips out HTML and PHP Tags and finally encodes the final result
 * using escaped HTML characters. This should be good enough to remove any XSS attack information
 *
 * @param mixed $input the input to clean
 * @return mixed the cleaned input information
 */
function kan_clean_input($input) {
    return nl2br(kan_make_plain(strip_tags(urldecode($input))));
}

/**
 * Fixes KAN Paths so they reference the document root of the site making them work
 * across folders much more easily
 *
 * @param string $url the URL to fix
 * @return string a url which references from the root of the site
 */
function kan_fix_path($path) {
    
    if (preg_match("/^\.\.\//", $path)) {
        return str_replace("../", BASE_PATH, $path);
    }

    return $path;
}

/**
 * Fixes KAN URLs so they reference the root of the site making them work both
 * with URL Rewriting and without
 *
 * @param string $url the URL to fix
 * @return string a url which references from the root of the site
 */
function kan_fix_url($url, $includeHost = false) {
    global $siteRoot, $siteHost;

    if (preg_match("/^\.\.\//", $url)) {
        $fixed = str_replace('../', $siteRoot, $url);

        if ($includeHost) {
            return $siteHost . $fixed;
        }

        if (defined("PREVIEW_MODE") && PREVIEW_MODE == true) {
            $fixed .= strpos($fixed, "?") > 0 ? "&" : "?";
            $fixed .= "preview=true";
        }

        return $fixed;
    }

    if (defined("PREVIEW_MODE") && PREVIEW_MODE == true) {
        $url .= strpos($url, "?") > 0 ? "&" : "?";
        $url .= "preview=true";
    }

    return $url;
}

/**
 * Formats the specified url to include the preview parameter to enable
 * the PREVIEW_MODE
 * 
 * @param string $url
 * @return string 
 */
function kan_preview_url($url) {
    $url = kan_fix_url($url);

    $url .= strpos($url, "?") > 0 ? "&" : "?";
    $url .= "preview=true";

    return $url;
}

/**
 * Returns a parameter from the PHP Global Arrays if present. It checks in the order
 * GET, POST, SESSION and then COOKIE and returns the value of the parameter if found.
 * If the paramter is not found, it returns an empty string or the default value specified.
 *
 * If the parameter is found as a GET variable, it will be cleaned before being returned,
 * saving the developer at least one security step. If the value found is a POST or COOKIE
 * variable, it will simply be attempt to convert it to plain text so can still be saved to
 * the database and outputted later.vSESSION variables are however, returned just as 
 * they were saved for now.
 *
 * @param string $param the parameter key
 * @param string $default the default value to return if parameter is not found
 * @return mixed the value of the parameter if found or the default value specified
 */
function kan_get_parameter($param, $default = '') {

    if (isset($_GET[$param])) {
        return kan_clean_input($_GET[$param]);
    } else if (isset($_POST[$param])) {
        return kan_clean_input($_POST[$param]);
    } else if (isset($_SESSION[$param])) {
        return $_SESSION[$param];
    } else if (isset($_COOKIE[$param])) {
        return kan_make_plain($_COOKIE[$param]);
    }

    return $default;
}

/**
 * Returns the URL to the home page of the current KAN site
 */
function kan_site_home() {
    if (SEF_URLS) {
        return kan_fix_url("../" . SITE_TAG . "/");
    }

    return kan_fix_url('../pages/index.php?siteid=' . SITE_TAG);
}

/**
 * Enables the KAN themes to get a component for inclusion without having to manually
 * build the reference to the Component file.
 *
 * Added for backup compartibility for older KAN installations that make use of this
 * function from the old Components.php file
 */
function getComponent($key) {
    global $compManager;

    return $compManager->getComponentPath($key);
}

/**
 *  Returns the value of a system setting based on the $key specified
 *
 * @param mixed $key the setting key
 * @param mixed $default the default value to return if the setting is not found
 * @return mixed returns the value of the setting specified by the key
 */
function getSetting($key, $default = NULL) {
    global $system;

    $setting = $system->getSetting($key);

    if ($setting) {
        return $setting;
    }

    return $default;
}

function kan_process_html($html) {

    $html = kan_fix_component_references($html);
    $html = kan_fix_relative_paths($html);

    return $html;
}

/**
 * Processes the supplied HTML content and replaces the tags references
 * for the various components, with their actual rendered HTML.
 * 
 * @global Site $site the global site object
 * @global ComponentManager $compManager the global component manager
 * @param string $html the content to be cleaned
 */
function kan_fix_component_references($html) {
    global $site, $compManager;

    // find all component references in the HTML
    $matches = array();
    preg_match_all('~\{\{\!(.*?)\!\}\}~', $html, $matches);

    $patterns = $matches[0];
    $comp_ids = $matches[1];

    for ($ix = 0; $ix < count($comp_ids); $ix++) {
        $key = $comp_ids[$ix];
		
        // get a reference to the component object itself
        $component = $compManager->getComponent($key);
		
		if( isset($component) ) {
			$site->component = $component; // cache component for later use

			ob_start();
			include( $component->getPath() );
			$eval_buffer = ob_get_contents(); // obtain the result of the evaluation
			ob_end_clean(); // empty the buffer
	
			$html = str_replace($patterns[$ix], $eval_buffer, $html);
		}
    }

    return $html;
}

/**
 * Processes the supplied HTML Content, and fixes all references such that
 * they point to the DOCUMENT ROOT of the site, instead of the relative reference
 * used when developing.
 *
 * @param mixed $content a string contain the HTML of the content
 * @return mixed the HTML containing the fixed paths
 */
function kan_fix_relative_paths($content) {

    $matches = array();
    preg_match_all("~\\.\\.\\/(.*?)\\/~", $content, $matches);

    $folders = $matches[1];
    $replacements = array();

    foreach ($folders as $folder) {
        $replacement = SITE_ROOT . $folder . "/";

        if (!in_array($replacement, $replacements)) {
            $replacements[] = $replacement;
        }
    }

    $matches = $matches[0];
    $patterns = array();

    foreach ($matches as $match) {
        $pattern = "/" . str_replace("/", "\/", $match) . "/";

        if (!in_array($pattern, $patterns)) {
            $patterns[] = $pattern;
        }
    }

    $fixed = preg_replace($patterns, $replacements, $content);

    return $fixed;
}

/**
 * This filters a string into a "friendly" string for use in URL's. It converts the 
 * string to lower case and replaces any non-alphanumeric (and accented) characters with dashes.
 *
 * http://snipplr.com/view/2809/convert-string-to-slug/
 */
function slug($str) {
    $str = strtolower(trim($str));
    $str = preg_replace('/[^a-z0-9-]/', '-', $str);
    $str = preg_replace('/-+/', "-", $str);
    return $str;
}

function debug($data) {
	echo "<pre>";
	
	$calledFrom = debug_backtrace();
	$root = str_replace("\\", "/", $_SERVER['DOCUMENT_ROOT']);
	$file = str_replace("\\", "/", $calledFrom[0]['file']);

	echo '<strong>' . str_replace($root, '/', $file) . '</strong>';
	echo ' (line <strong>' . $calledFrom[0]['line'] . '</strong>) <br /><br />';
	
	print_r($data);	
	
	echo "</pre>";
}

?>